/* ats.c: fontman engine, Mac OS X ATS only */

#include "libfontman.h"
#include "internal.h"

extern fontman_list_t list_context;
extern struct fontman_sfnt_name sfnt_name_combination[];

int fontman_list_platform_init()
{
    OSStatus status = noErr;

    status = ATSFontIteratorCreate(kATSFontContextGlobal, 
                                   NULL, 
                                   NULL, 
                                   kATSOptionFlagsUnRestrictedScope, 
                                   &list_context.u.iterator);
    if (status != noErr)
        return FONTMAN_ERR_PLATFORM_INIT;

    return 0;
}

void fontman_list_platform_free()
{
    ATSFontIteratorRelease(&list_context.u.iterator);
}

int get_path(fontman_face_t *face, ATSFontRef ref)
{
    FSSpec      fSpec;
    FSRef       fRef;
    OSStatus    status;

    status = ATSFontGetFileSpecification(ref, &fSpec);

    if (status != noErr)
        return FONTMAN_ERR_GET_PATH;

    status = FSpMakeFSRef(&fSpec, &fRef);
    if (status != noErr)
        return FONTMAN_ERR_GET_PATH;
    
    status = FSRefMakePath(&fRef, (UInt8 *) face->path, PATH_MAX - 1);
    if (status != noErr)
        return FONTMAN_ERR_GET_PATH;

    return 0;
}

int fontman_list_platform_next(fontman_face_t *face)
{
    ATSFontRef  ref;
    OSStatus    status;
    CFStringRef	name, ps_name;
    int         encoding = FONTMAN_OUTPUT_ENCODING;
    unsigned int flags = list_context.flags;

    status = ATSFontIteratorNext(list_context.u.iterator, &ref);

    if (status != noErr)
        return FONTMAN_ERR_NO_NEXT;

    if (flags & FONTMAN_GET_NAME)
    {
        /* get font name */
        ATSFontGetName(ref, kATSOptionFlagsDefault, &name);
        CFStringGetCString(name, face->name, FONTMAN_MAX_FONT_NAME, 
                           encoding);
        CFRelease(name);
    }

    if (flags & FONTMAN_GET_PS_NAME)
    {
        /* get font ps name */
        ATSFontGetPostScriptName(ref, kATSOptionFlagsDefault, &ps_name);
        CFStringGetCString(ps_name, face->ps_name, 
                           FONTMAN_MAX_PS_NAME, encoding);
        CFRelease(ps_name);
    }

    if (flags & FONTMAN_GET_PATH)
    {
        /* get path */
        int err = get_path(face, ref);
        if (err)
            return err;
    }

    if (flags & FONTMAN_GET_LOCAL_NAME)
    {
        ATSUFontID fontID;
        int i, len;
        struct fontman_sfnt_name *item;
        char buf[FONTMAN_MAX_LOCAL_NAME];

        face->local_name[0] = '\0';
        fontID = FMGetFontFromATSFontRef(ref);

        for (i = 0; 
             item = &sfnt_name_combination[i], 
             item->platform_id != FONTMAN_SFNT_END; i++)
        {
            status = ATSUFindFontName(fontID, 
                                      item->name_id, 
                                      item->platform_id,
                                      item->encoding_id,
                                      item->language_id, 
                                      FONTMAN_MAX_LOCAL_NAME, 
                                      buf, (ByteCount *) &len, NULL);

            if (status == noErr)
            {
                convert_sfnt_name(face->local_name, 
                                  buf, len, 
                                  /* it's tricky here: the encoding 
                                   * actually store in the font is 
                                   * bigger endian, but ATSUI will 
                                   * automatically convert it into
                                   * little endian */
                                  item->enc_id == FONTMAN_ENC_UTF16BE ? 
                                  FONTMAN_ENC_UTF16LE : item->enc_id);
                goto done;
            }
        }

        /* no local font name found, exclude this font if no 
         * FONTMAN_INCLUDE_ALL specified as flag */
        if (! (flags & FONTMAN_INCLUDE_ALL))
            return fontman_list_platform_next(face);
    }

done:
    return 0;
}

int fontman_info_platform_font(fontman_face_t *face)
{
    ATSFontRef  ref;
    CFStringRef	name;
    int         encoding = FONTMAN_OUTPUT_ENCODING;
    int         err;

    name = CFStringCreateWithCString(NULL, face->name, encoding);

    ref = ATSFontFindFromName(name, 
                              kATSOptionFlagsUnRestrictedScope);

    CFRelease(name);

    /* this way of determination is from FreeType library */
    if ((long) ref <= 0)
    {
        fprintf(stderr, "font not found\n");
        return FONTMAN_ERR_FIND_FONT;
    }

    err = get_path(face, ref);
    if (err)
        return err;

    /* no need to get name */
    return fontman_info_file(face, 
                             FONTMAN_GET_ALL & ~FONTMAN_GET_NAME);
}

